package com.ruoyi.project.modules.table.controller;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysDictType;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.modules.businessSystem.domain.BusinessSystem;
import com.ruoyi.project.modules.businessSystem.service.IBusinessSystemService;
import com.ruoyi.project.modules.fieldEnum.service.IFieldEnumService;
import com.ruoyi.project.modules.interfaceObject.domain.InterfaceObject;
import com.ruoyi.project.modules.interfaceObject.service.IInterfaceObjectService;
import com.ruoyi.project.modules.interfaceinfo.domain.InterfaceInfo;
import com.ruoyi.project.modules.interfaceinfo.service.IInterfaceInfoService;
import com.ruoyi.project.modules.interfaceinfo.vo.InterfaceUser;
import com.ruoyi.project.modules.page.domain.Page;
import com.ruoyi.project.modules.page.service.IPageService;
import com.ruoyi.project.modules.parameter.domain.InterfaceParamsFieldRelation;
import com.ruoyi.project.modules.parameter.domain.ParamsFieldRelation;
import com.ruoyi.project.modules.parameter.service.IInterfaceParamsFieldRelationService;
import com.ruoyi.project.modules.parameter.service.IParamsFieldRelationService;
import com.ruoyi.project.modules.table.domain.FieldInfo;
import com.ruoyi.project.modules.table.domain.FieldStatus;
import com.ruoyi.project.modules.table.domain.ParseSqlAddSaveReqDto;
import com.ruoyi.project.modules.table.service.IFieldStatusService;
import com.ruoyi.project.modules.table.vo.TableInterfaceVo;
import com.ruoyi.project.modules.tableIndex.service.ITableIndexService;
import com.ruoyi.project.modules.tableObject.domain.TableObject;
import com.ruoyi.project.modules.tableObject.service.ITableObjectService;
import com.ruoyi.project.modules.tableRelation.domain.TableRelation;
import com.ruoyi.project.modules.tableRelation.service.ITableRelationService;
import com.ruoyi.project.modules.usage.domain.Usage;
import com.ruoyi.project.modules.userDataAuth.service.IUserDataAuthService;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysDictTypeService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.project.modules.table.domain.TableInfo;
import com.ruoyi.project.modules.table.service.ITableInfoService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;

import com.alibaba.druid.sql.ast.SQLStatement;

import java.util.ArrayList;
import java.util.List;

/**
 * 类对象信息Controller
 *
 * @author smallrain
 * @date 2021-10-28
 */
@Controller
@RequestMapping("/table/table")
public class TableInfoController extends BaseController {
    private String prefix = "table/table";

    @Autowired
    private ITableInfoService tableInfoService;
    @Autowired
    private IBusinessSystemService businessSystemService;
    @Autowired
    private IPageService pageService;
    @Autowired
    private IInterfaceInfoService interfaceInfoService;
    @Autowired
    private IFieldStatusService fieldStatusService;
    @Autowired
    private IFieldEnumService fieldEnumService;
    @Autowired
    private ITableRelationService tableRelationService;

    @RequiresPermissions("table:table:view")
    @GetMapping()
    public String table() {
        return prefix + "/table";
    }

    private String captureDateType(SQLDataType dataType){
        if(dataType.getName().equals("varchar")){
            return "1";
        }else if(dataType.getName().equals("bigint")){
            return "2";
        }else if(dataType.getName().equals("datetime")){
            return "3";
        }
        return "1";
    }

    private String captureDateLength(SQLDataType dataType){
        List<SQLExpr> sqlexList = dataType.getArguments();
        if(CollectionUtil.isNotEmpty(sqlexList)){
            SQLExpr elm = sqlexList.get(0);
            if(ObjectUtils.isNotEmpty(elm)){
                return String.valueOf(elm);
            }
        }
        return "0";
    }

    /**
     * 解析sql语句
     *
     * @param statement
     * @return
     */
    public TableInfo parse(String statement) {
        TableInfo table = new TableInfo();
        // 使用druid解析语句
        // 第一个参数为SQL语句
        // 第二个参数为解析的数据库类型
        List<SQLStatement> statementList = SQLUtils.parseStatements(statement, JdbcConstants.SQL_SERVER);
        // 单语句解析，只有一条数据
        if (!statement.isEmpty()) {
            SQLStatement sqlStatement = statementList.get(0);
            // 插入语句解析
            if (sqlStatement instanceof SQLCreateTableStatement) {
                table = new TableInfo();
                List<FieldInfo> fieldList = new ArrayList<>();
                table.setFieldInfoList(fieldList);
                // 转换
                SQLCreateTableStatement insertStatement = (SQLCreateTableStatement) sqlStatement;
                table.setTableName("临时表");
                table.setTableEnName(((SQLCreateTableStatement) sqlStatement).getTableName().replaceAll("`","").replaceAll("`",""));
                table.setAliasName(UUID.randomUUID().toString());
                // 获取列名
                List<SQLColumnDefinition> columns = insertStatement.getColumnDefinitions();
                int count = 1;
                for (SQLColumnDefinition column : columns) {
                    FieldInfo field = new FieldInfo();
                    if(column.getComment()==null){
                        field.setFieldName("填充");
                    }else{
                        field.setFieldName(column.getComment().toString().replaceAll("'","").replaceAll("'",""));
                    }

                    field.setFieldEnName(column.getColumnName().replaceAll("`","").replaceAll("`",""));
                    field.setCategory("1");
                    field.setIsFieldStatus("N");
                    field.setIsFieldEnum("N");
                    field.setDictId(0L);
                    if(column.isOnlyPrimaryKey()){
                        field.setFieldType("1");
                    }else{
                        field.setFieldType("3");/** 字段类型（1主键 2外键 3属性） */
                    }
                    field.setFkFieldType("3");
                    field.setFieldDataType(captureDateType(column.getDataType()));
                    field.setFieldLength(captureDateLength(column.getDataType()));
                    field.setMysqlFieldDataType(column.getDataType().getName());
                    field.setMysqlFieldLength(field.getFieldLength());
                    field.setMockData("222");
                    field.setMockDescription("mock-data");
                    field.setIsChange("N");
                    field.setIsRequired("Y");
                    field.setIsInParam("Y");
                    field.setIsRisk("N");
                    field.setRecordIndex(0);
                    fieldList.add(field);
                    count++;
                }

            }
        }
        return table;
    }
//
//
//    public static void main(String[] args) throws Exception {
//        TableInfoController o = new TableInfoController();
//
//        TableInfo table = o.parse("CREATE TABLE `t_interface_info` (\n" +
//                "  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',\n" +
//                "  `appType` varchar(30) DEFAULT NULL COMMENT '应用类型',\n" +
//                "  `domain` varchar(255) DEFAULT NULL COMMENT '归属域',\n" +
//                "  `interfaceName` varchar(150) NOT NULL COMMENT '接口名称',\n" +
//                "  `interfaceDescription` text COMMENT '接口描述',\n" +
//                "  `interfaceUrl` varchar(150) NOT NULL COMMENT '接口地址',\n" +
//                "  `fbType` char(1) DEFAULT NULL COMMENT '前后类型（1-method 2-bff 3-dubbo）',\n" +
//                "  `optType` char(1) DEFAULT NULL COMMENT '操作类型（1增 2删 3改 4查）',\n" +
//                "  `interfaceType` char(1) DEFAULT NULL COMMENT '接口类型（1get 2post 3put 4delete）',\n" +
//                "  `isRisk` char(1) DEFAULT 'N' COMMENT '是否风险接口',\n" +
//                "  `isPage` char(1) DEFAULT NULL COMMENT '是否分页（Y是 N否）',\n" +
//                "  `total` int(11) DEFAULT NULL COMMENT '总条数',\n" +
//                "  `page` int(11) DEFAULT NULL COMMENT '页数',\n" +
//                "  `pageSize` int(11) DEFAULT NULL COMMENT '每页大小',\n" +
//                "  `nonFunctionalRequirements` text COMMENT '非功能需求',\n" +
//                "  `isTree` char(1) DEFAULT 'N' COMMENT '是否返回树形结构(Y-是 N-否)',\n" +
//                "  `specialInterface` varchar(30) DEFAULT NULL COMMENT '特殊接口',\n" +
//                "  `inParamDtoName` varchar(255) DEFAULT NULL COMMENT '入参DTO名称',\n" +
//                "  `outParamDtoName` varchar(255) DEFAULT NULL COMMENT '出参DTO名称',\n" +
//                "  `isBoundary` char(1) DEFAULT 'N' COMMENT '是否边界',\n" +
//                "  `isCommon` char(1) DEFAULT 'N' COMMENT '是否公共',\n" +
//                "  `isPlatform` char(1) DEFAULT 'N' COMMENT '是否平台',\n" +
//                "  `isManage` char(1) DEFAULT 'N' COMMENT '是否管理',\n" +
//                "  `domainId` bigint(20) DEFAULT NULL COMMENT '归属域id',\n" +
//                "  `domainObjectId` bigint(20) DEFAULT NULL COMMENT '归属对象id',\n" +
//                "  `operateType` varchar(100) DEFAULT NULL COMMENT '动词',\n" +
//                "  `isBranch` char(1) DEFAULT 'N' COMMENT '是否是分支',\n" +
//                "  `status` char(1) DEFAULT '1' COMMENT '状态（1未开始 2进行中 3已完成）',\n" +
//                "  `lifeCycle` varchar(30) DEFAULT NULL COMMENT '1-设计中、2-设计完成、3-评审环节、4-待生成代码、5-生成代码待验证、6-单元测试未开始、7-前端待测试、8-完成前端测试、9-接口封版',\n" +
//                "  `errorStatus` varchar(30) DEFAULT NULL COMMENT '1-无状态、2-正常状态、3-代码概要验证异常、4-单元测试异常、5-前端测试异常、6-正常后异常',\n" +
//                "  `preLifeCycle` varchar(30) DEFAULT '10' COMMENT '设计状态',\n" +
//                "  `isEditTest` varchar(10) DEFAULT NULL COMMENT '是否编辑测试',\n" +
//                "  `del_flag` char(1) DEFAULT '0' COMMENT '删除标志（0代表存在 2代表删除）',\n" +
//                "  `create_by` varchar(64) DEFAULT '' COMMENT '创建者',\n" +
//                "  `create_time` datetime DEFAULT NULL COMMENT '创建时间',\n" +
//                "  `update_by` varchar(64) DEFAULT '' COMMENT '更新者',\n" +
//                "  `update_time` datetime DEFAULT NULL COMMENT '更新时间',\n" +
//                "  `storageType` varchar(100) DEFAULT NULL COMMENT '页面存储类型-字典',\n" +
//                "  `isJob` varchar(10) DEFAULT NULL COMMENT '是否是定时任务',\n" +
//                "  `jobDescription` varchar(1000) DEFAULT NULL COMMENT '定时任务描述',\n" +
//                "  PRIMARY KEY (`id`)\n" +
//                ")");
////        o.parse("insert into test (id,status,name,ce,acc) values (29,'P','lll','sxsx','Arferwg')");
//        System.out.println(table);
//        o.addSave(table);
//    }

    /**
     * 查询类对象信息列表
     */
    //@RequiresPermissions("table:table:list")
    @PostMapping("/parsesqladdsave")
    @ResponseBody
    public AjaxResult parseSqlAddSaveReqDto(@RequestBody ParseSqlAddSaveReqDto req) {
        TableInfo table = parse(req.getSql());
        addSave(table);
        return AjaxResult.success();
    }


    /**
     * 查询类对象信息列表
     */
    //@RequiresPermissions("table:table:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(TableInfo tableInfo) {
        startPage();
        tableInfo.setUserId(ShiroUtils.getSysUser().getUserId());
        tableInfo.setAuthflag(this.getFlag());

        List<TableInfo> list = tableInfoService.selectTableInfoList(tableInfo);
        return getDataTable(list);
    }

    /**
     * 导出类对象信息列表
     */
    @RequiresPermissions("table:table:export")
    @Log(title = "类对象信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ResponseBody
    public AjaxResult export(TableInfo tableInfo) {
        List<TableInfo> list = tableInfoService.selectTableInfoList(tableInfo);
        ExcelUtil<TableInfo> util = new ExcelUtil<TableInfo>(TableInfo.class);
        return util.exportExcel(list, "类对象信息数据");
    }

    /**
     * 新增类对象信息
     */
    @GetMapping("/add")
    public String add(ModelMap mmap) {
        mmap.put("aliasName", UUID.randomUUID().toString().replace("-",""));
        return prefix + "/add";
    }

    /**
     * 新增保存类对象信息
     */

    @RequiresPermissions("table:table:add")
    @Log(title = "类对象信息", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(TableInfo tableInfo) {
        tableInfo.setIsEncry("TRUE");
        return toAjax(tableInfoService.insertTableInfo(tableInfo));
    }

    /**
     * 修改类对象信息
     */
    @GetMapping("/edit/{id}")
    public String edit(@PathVariable("id") Long id, ModelMap mmap) {
        TableInfo tableInfo = tableInfoService.selectTableInfoById(id);
        Map<Integer, String> tableRelationInfoObj = new HashMap<>();
        List<FieldInfo> fieldInfoList = tableInfo.getFieldInfoList();
        if (CollectionUtil.isNotEmpty(fieldInfoList)) {
            for (int i = 0; i< fieldInfoList.size(); i++) {
                if ("2".equals(fieldInfoList.get(i).getFieldType())) {
                    TableRelation tableRelation = new TableRelation();
                    tableRelation.setMasterFieldId(fieldInfoList.get(i).getId());
                    List<TableRelation> tableRelationList = this.tableRelationService.selectTableRelationList(tableRelation);
                    if (CollectionUtil.isNotEmpty(tableRelationList)) {
                        tableRelationInfoObj.put(i, JSONObject.toJSONString(tableRelationList));
                    }
                }
            }
        }
        tableInfo.setTableRelationInfo(JSONObject.toJSONString(tableRelationInfoObj));
        mmap.put("tableInfo", tableInfo);
        mmap.put("tableRelationInfoObj", tableRelationInfoObj);
        return prefix + "/edit";
    }

    /**
     * 修改保存类对象信息
     */
    @RequiresPermissions("table:table:edit")
    @Log(title = "类对象信息", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(TableInfo tableInfo) {
        TableInfo info = tableInfoService.selectTableInfoById(tableInfo.getId());
        if (CollectionUtil.isNotEmpty(info.getFieldInfoList())) {
            List<Long> longs = new ArrayList<>();
            if (!CollectionUtil.isNotEmpty(tableInfo.getFieldInfoList())) {
                longs = info.getFieldInfoList().stream().map(FieldInfo::getId).collect(Collectors.toList());
            } else {
                Map<Long, Boolean> reqMap = new HashMap<>();
                for (FieldInfo fieldInfo : tableInfo.getFieldInfoList()) {
                    if (fieldInfo.getId() != null) {
                        reqMap.put(fieldInfo.getId(), true);
                    }
                }
                for (FieldInfo fieldInfo : info.getFieldInfoList()) {
                    if (!reqMap.containsKey(fieldInfo.getId())) {
                        longs.add(fieldInfo.getId());
                    }
                }
            }
            if (CollectionUtil.isNotEmpty(longs)) {
                InterfaceParamsFieldRelation interfaceParamsFieldRelation = new InterfaceParamsFieldRelation();
                interfaceParamsFieldRelation.setFieldIds(longs);
                interfaceParamsFieldRelation.setObjectType("1");
                List<InterfaceParamsFieldRelation> interfaceParamsFieldRelations = interfaceParamsFieldRelationService.selectInterfaceParamsFieldRelationList(interfaceParamsFieldRelation);
                if (CollectionUtil.isNotEmpty(interfaceParamsFieldRelations)) {
                    return AjaxResult.warn("字段与接口有关联,请解除关联");
                }
                ParamsFieldRelation paramsFieldRelation = new ParamsFieldRelation();
                paramsFieldRelation.setFieldIds(longs);
                List<ParamsFieldRelation> paramsFieldRelationList = paramsFieldRelationService.selectParamsFieldRelationList(paramsFieldRelation);
                if (CollectionUtil.isNotEmpty(paramsFieldRelationList)) {
                    return AjaxResult.warn("字段与接口有关联,请解除关联");
                }
            }
        }
        return toAjax(tableInfoService.updateTableInfo(tableInfo));
    }

    @Autowired
    private ITableObjectService tableObjectService;

    @Autowired
    private IInterfaceObjectService interfaceObjectService;

    @Autowired
    private IUserDataAuthService userDataAuthService;

    /**
     * 删除类对象信息
     */
    @RequiresPermissions("table:table:remove")
    @Log(title = "类对象信息", businessType = BusinessType.DELETE)
    @PostMapping("/remove")
    @ResponseBody
    public AjaxResult remove(String ids) {
        Set<Long> longs = Convert.toLongSet(ids);
        TableInfo tableInfo = this.tableInfoService.selectTableInfoById(Long.parseLong(ids));
        if (CollectionUtil.isNotEmpty(tableInfo.getFieldInfoList())) {
            return AjaxResult.warn("表里有字段,请解除关联");
        }
        TableObject tableObject = new TableObject();
        tableObject.setTableIds(longs);
        List<TableObject> tableObjects = this.tableObjectService.selectTableObjectList(tableObject);
        if (CollectionUtil.isNotEmpty(tableObjects)) {
            return AjaxResult.warn("表对象与业务系统有关联,请解除关联");
        }
        InterfaceObject interfaceObject = new InterfaceObject();
        interfaceObject.setTableIds(new ArrayList<>(longs));
        interfaceObject.setObjectType("1");
        List<InterfaceObject> interfaceObjectList = this.interfaceObjectService.selectInterfaceObjectList(interfaceObject);
        if (CollectionUtil.isNotEmpty(interfaceObjectList)) {
            return AjaxResult.warn("表对象与接口有关联,请解除关联");
        }
        return toAjax(tableInfoService.deleteTableInfoByIds(ids));
    }

    @Autowired
    private IInterfaceParamsFieldRelationService interfaceParamsFieldRelationService;

    @Autowired
    private IParamsFieldRelationService paramsFieldRelationService;

    @Autowired
    private ITableIndexService tableIndexService;

    @PostMapping("/checkField")
    @ResponseBody
    public AjaxResult checkField(String fieldIds) {
        List<Long> longs = Convert.toLongList(fieldIds);
        InterfaceParamsFieldRelation interfaceParamsFieldRelation = new InterfaceParamsFieldRelation();
        interfaceParamsFieldRelation.setFieldIds(longs);
        interfaceParamsFieldRelation.setObjectType("1");
        List<InterfaceParamsFieldRelation> interfaceParamsFieldRelations = interfaceParamsFieldRelationService.selectInterfaceParamsFieldRelationList(interfaceParamsFieldRelation);
        if (CollectionUtil.isNotEmpty(interfaceParamsFieldRelations)) {
            return AjaxResult.warn("字段与接口有关联,请解除关联");
        }
        ParamsFieldRelation paramsFieldRelation = new ParamsFieldRelation();
        paramsFieldRelation.setFieldIds(longs);
        List<ParamsFieldRelation> paramsFieldRelationList = paramsFieldRelationService.selectParamsFieldRelationList(paramsFieldRelation);
        if (CollectionUtil.isNotEmpty(paramsFieldRelationList)) {
            return AjaxResult.warn("字段与接口有关联,请解除关联");
        }
        boolean exist = this.tableIndexService.checkField(longs);
        if (exist) {
            return AjaxResult.warn("字段与表索引有关联,请解除关联");
        }
        return toAjax(1);
    }

    /**
     * 表详情；
     * fieldInfoList ：字段信息列表
     * 在模型预览和字段属性展示
     * @param id 表id
     * @param mmap mmap
     * @return 表详情页面
     */
    @GetMapping("/detail/{id}")
    public String detail(@PathVariable("id") Long id, ModelMap mmap) {
        TableInfo tableInfo = this.tableInfoService.selectTableInfoById(id);
        mmap.put("tableInfo", tableInfo);
        List<InterfaceUser> interfaceUsers = this.userDataAuthService.selectInterfaceUser(id, "4");
        if (CollectionUtil.isNotEmpty(interfaceUsers)) {
            for (InterfaceUser interfaceUser : interfaceUsers) {
                if (ShiroUtils.getLoginName().equals(interfaceUser.getLoginName())) {
                    mmap.put("owner", true);
                    mmap.put("interfaceUser", interfaceUser);

                    if (interfaceUser.getObjectStatus() == 0) {
                        mmap.put("statusName", "未开始");
                    } else if (interfaceUser.getObjectStatus() == 1) {
                        mmap.put("statusName", "进行中");
                    } else if (interfaceUser.getObjectStatus() == 2) {
                        mmap.put("statusName", "已完成");
                    }
                    break;
                }
            }
        }
        return prefix + "/detail";
    }

    @PostMapping("/updateTableStatus")
    @ResponseBody
    public AjaxResult updateTableStatus(TableInfo tableInfo) {
        this.tableInfoService.updateTableStatus(tableInfo);
        return success();
    }

    @PostMapping("/fieldInfoList")
    @ResponseBody
    public AjaxResult fieldInfoList(FieldInfo fieldInfo) {
        if (fieldInfo.getInterfaceId() != null) {
            InterfaceInfo interfaceInfo = interfaceInfoService.selectInterfaceInfoById(fieldInfo.getInterfaceId());
            if ("4".equals(interfaceInfo.getOptType()) && "Y".equals(fieldInfo.getIsInParam())) {
                fieldInfo.setIsInParam("Y");
            } else {
                fieldInfo.setIsInParam(null);
            }
        } else {
            fieldInfo.setIsInParam(null);
        }
        List<FieldInfo> fieldInfoList = this.tableInfoService.fieldInfoList(fieldInfo);
        if (CollectionUtil.isNotEmpty(fieldInfoList)) {
            for (FieldInfo info : fieldInfoList) {
                if ("1".equals(info.getFieldDataType())) {
                    info.setFieldDataType("文本");
                } else if ("2".equals(info.getFieldDataType())) {
                    info.setFieldDataType("数字");
                } else if ("3".equals(info.getFieldDataType())) {
                    info.setFieldDataType("日期");
                }
            }
        }
        return AjaxResult.success(fieldInfoList);
    }

    /**
     * 关联接口
     * @param tableId
     * @return
     */
    @PostMapping("/interfaceList")
    @ResponseBody
    public AjaxResult interfaceList(@RequestParam Long tableId) {
        List<InterfaceInfo> interfaceList = this.tableInfoService.interfaceList(tableId);
        List<InterfaceInfo> bffList = new ArrayList<>();
        List<InterfaceInfo> dubboList = new ArrayList<>();
        List<InterfaceInfo> methodList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(interfaceList)) {
            for (InterfaceInfo interfaceInfo : interfaceList) {
                if (interfaceInfo.getFbType().equals("2")) {
                    bffList.add(interfaceInfo);
                } else if (interfaceInfo.getFbType().equals("3")) {
                    dubboList.add(interfaceInfo);
                } else {
                    methodList.add(interfaceInfo);
                }
            }
        }
        return AjaxResult.success(new TableInterfaceVo(bffList, dubboList, methodList));
    }

    /**
     * 关联业务系统
     * @param tableId 表id
     * @return
     */
    @PostMapping("/businessSystemList")
    @ResponseBody
    public AjaxResult businessSystemList(@RequestParam Long tableId) {
        List<BusinessSystem> businessSystems = null;
        TableObject tableObject = new TableObject();
        tableObject.setObjectType("1");
        tableObject.setTableId(tableId);
        List<TableObject> tableObjects = this.tableObjectService.selectTableObjectList(tableObject);
        if (CollectionUtil.isNotEmpty(tableObjects)) {
            Set<Long> businessSystemIds = tableObjects.stream().map(TableObject::getObjectId).collect(Collectors.toSet());
            BusinessSystem businessSystem = new BusinessSystem();
            businessSystem.setBusinessSystemIds(businessSystemIds);
            businessSystems = businessSystemService.selectBusinessSystemList(businessSystem);
        }
        return AjaxResult.success(businessSystems);
    }

    /**
     * 关联页面
     * @param tableId 表id
     * @return
     */
    @PostMapping("/pageList")
    @ResponseBody
    public AjaxResult pageList(@RequestParam Long tableId) {
        List<InterfaceInfo> interfaceList = this.tableInfoService.interfaceList(tableId);
        List<Page> pageList = null;
        if (CollectionUtil.isNotEmpty(interfaceList)) {
            List<Long> interfaceIds = interfaceList.stream().map(InterfaceInfo::getId).collect(Collectors.toList());
            pageList = this.pageService.pageListByInterfaceId(interfaceIds);
        }
        return AjaxResult.success(pageList);
    }

    /**
     * 关联用况
     * @param tableId 表id
     * @return
     */
    @PostMapping("/usageList")
    @ResponseBody
    public AjaxResult usageList(@RequestParam Long tableId) {
        List<InterfaceInfo> interfaceList = this.tableInfoService.interfaceList(tableId);
        List<Usage> usageList = null;
        if (CollectionUtil.isNotEmpty(interfaceList)) {
            List<Long> interfaceIds = interfaceList.stream().map(InterfaceInfo::getId).collect(Collectors.toList());
            usageList = this.interfaceInfoService.selectUsageList(interfaceIds);
        }
        return AjaxResult.success(usageList);
    }

    @GetMapping("/queryFieldStatus/{fieldId}")
    public String queryFieldStatus(@PathVariable("fieldId") Long fieldId, ModelMap mmap) {
        FieldStatus fieldStatus = new FieldStatus();
        fieldStatus.setFieldId(fieldId);
        List<FieldStatus> fieldStatusList = this.fieldStatusService.selectFieldStatusList(fieldStatus);
        mmap.put("fieldStatusList", fieldStatusList);
        return prefix + "/queryFieldStatus";
    }

    @Autowired
    private ISysDictDataService sysDictDataService;

    @Autowired
    private ISysDictTypeService sysDictTypeService;

    @GetMapping("/queryFieldEnum/{dictId}")
    public String queryFieldEnum(@PathVariable("dictId") Long dictId, ModelMap mmap) {
//        FieldEnum fieldEnum = new FieldEnum();
//        fieldEnum.setFieldId(fieldId);
//        List<FieldEnum> fieldEnums = this.fieldEnumService.selectFieldEnumList(fieldEnum);
//        mmap.put("fieldEnums", fieldEnums);
        SysDictType sysDictType = this.sysDictTypeService.selectDictTypeById(dictId);
        List<SysDictData> sysDictDatas = new ArrayList<>();
        if (sysDictType != null) {
            SysDictData dictData = new SysDictData();
            dictData.setDictType(sysDictType.getDictType());
            sysDictDatas = this.sysDictDataService.selectDictDataList(dictData);
        }
        mmap.put("sysDictDatas", sysDictDatas);
        return prefix + "/queryFieldEnum";
    }

    @GetMapping("/queryFKRelation/{fieldId}")
    public String queryFKRelation(@PathVariable("fieldId") Long fieldId, ModelMap mmap) {
        TableRelation tableRelation = new TableRelation();
        tableRelation.setMasterFieldId(fieldId);
        List<TableRelation> tableRelationList = this.tableRelationService.selectTableRelationList(tableRelation);
        mmap.put("tableRelationList", tableRelationList);
        return prefix + "/queryFKRelation";
    }

    @GetMapping("/setFkRelation")
    public String setFkRelation(String fkFieldInfo, Integer index, Long tableId, ModelMap mmap) {
        mmap.put("index", index);
        if (tableId != null) {
            mmap.put("tableId", tableId);
        }
        List<TableRelation> tableRelationList = new ArrayList<>();
        if (StringUtils.isNotEmpty(fkFieldInfo)) {
            tableRelationList = JSONObject.parseArray(fkFieldInfo, TableRelation.class);
        }
        mmap.put("tableRelationList", tableRelationList);
        return prefix + "/setFkRelation";
    }

    @GetMapping("field_choose")
    public String field_choose(Long tableId, ModelMap mmap) {
        TableInfo tableInfo = new TableInfo();
//        if (tableId != null) {
//            tableInfo.setExcludeIds(Collections.singletonList(tableId));
//        }
        List<TableInfo> tableInfos = this.tableInfoService.selectTableInfoList(tableInfo);
        mmap.put("tableInfoList", tableInfos);
        return prefix + "/field_choose";
    }

    @PostMapping("/fieldList")
    @ResponseBody
    public TableDataInfo fieldList(Long tableId) {
        TableInfo tableInfo = this.tableInfoService.selectTableInfoById(tableId);
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(0);
        rspData.setRows(tableInfo.getFieldInfoList());
        rspData.setTotal(tableInfo.getFieldInfoList().size());
        return rspData;
    }

    @GetMapping("/selectFieldEnum")
    public String selectFieldEnum(Long dictId, ModelMap mmap) {
        mmap.put("dictId", dictId);
        return prefix + "/selectFieldEnum";
    }

    @GetMapping("/tableRef/{id}/{type}")
    public String tableReByType(@PathVariable("type") int type,@PathVariable("id") int tableId, ModelMap mmap) {
        mmap.put("type", type);
        mmap.put("tableId", tableId);
        return prefix + "/table_relation";
    }

    /**
     * 表模型关系
     * @param tableId
     * @return
     */
    @PostMapping("/tableRef")
    @ResponseBody
    public Map<String, Object> tableRef(Long tableId) {
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> nodeDataArray = new ArrayList<>();
        List<Map<String, String>> linkDataArray = new ArrayList<>();
        // 查询主表数据
        TableInfo tableInfo = this.tableInfoService.selectTableInfoById(tableId);
        nodeDataArray.add(convert(tableInfo));
        String from = getNodeName(tableInfo);

        TableRelation tableRelation = new TableRelation();
        tableRelation.setMasterTableId(tableId);
        List<TableRelation> tableRelationList = this.tableRelationService.selectTableRelationList(tableRelation);
        if (CollectionUtil.isNotEmpty(tableRelationList)) {
            Map<Long, List<FieldInfo>> fieldInfoMap = tableInfo.getFieldInfoList().stream().collect(Collectors.groupingBy(FieldInfo::getId));
            List<Long> tableIds = new ArrayList<>();
            for (TableRelation relation : tableRelationList) {
                List<FieldInfo> fieldInfoList = fieldInfoMap.get(relation.getMasterFieldId());
                if (CollectionUtil.isNotEmpty(fieldInfoList)) {
                    if ("2".equals(fieldInfoList.get(0).getFieldType()) && "1".equals(fieldInfoList.get(0).getFkFieldType())) {
                        tableIds.add(relation.getSlaveTableId());
                    }
                }
            }
            if (tableIds.size() > 0) {
                // 查询关联表数据
                List<TableInfo> tableInfos = this.tableInfoService.selectTableInfoByTableIds(new ArrayList<>(tableIds));
                if (CollectionUtil.isNotEmpty(tableInfos)) {
                    for (TableInfo info : tableInfos) {
                        Map<String, String> link = new HashMap<>();
                        String to = getNodeName(info);
                        link.put("from", from);
                        link.put("to", to);
                        linkDataArray.add(link);
                        nodeDataArray.add(convert(info));
                    }
                }
            }
        }
        result.put("nodeDataArray", nodeDataArray);
        result.put("linkDataArray", linkDataArray);
        return result;
    }

    /**
     * 表模型关系（关联我的）
     * @param tableId
     * @return
     */
    @PostMapping("/tableRef2")
    @ResponseBody
    public Map<String, Object> tableRef2(Long tableId) {
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> nodeDataArray = new ArrayList<>();
        List<Map<String, String>> linkDataArray = new ArrayList<>();
        // 查询主表数据
        TableInfo tableInfo = this.tableInfoService.selectTableInfoById(tableId);
        nodeDataArray.add(convert(tableInfo));
        String to = getNodeName(tableInfo);

        List<TableRelation> tableRelationList = this.tableInfoService.selectTableInfoByRelation(tableId);
        List<FieldInfo> coreFieldList = tableInfo.getFieldInfoList().stream().filter(field->field.getFkFieldType().equals("1")).collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(coreFieldList)){
            Map<Long, FieldInfo> coreFieldIndex = coreFieldList.stream().collect(Collectors.toMap(FieldInfo::getId, Function.identity(), (key1, key2) -> key2 ));
            tableRelationList = tableRelationList.stream().filter(r->coreFieldIndex.containsKey(r.getSlaveFieldId())).collect(Collectors.toList());
        }
        if (CollectionUtil.isNotEmpty(tableRelationList)) {
            List<Long> tableIds = tableRelationList.stream().map(TableRelation::getMasterTableId).collect(Collectors.toList());
            if (tableIds.size() > 0) {
                // 查询关联表数据
                List<TableInfo> tableInfos = this.tableInfoService.selectTableInfoByTableIds(new ArrayList<>(tableIds));
                if (CollectionUtil.isNotEmpty(tableInfos)) {
                    for (TableInfo info : tableInfos) {
                        Map<String, String> link = new HashMap<>();
                        String from = getNodeName(info);
                        link.put("from", from);
                        link.put("to", to);
                        linkDataArray.add(link);
                        nodeDataArray.add(convert(info));
                    }
                }
            }
        }
        result.put("nodeDataArray", nodeDataArray);
        result.put("linkDataArray", linkDataArray);
        return result;
    }

    private String getNodeName(TableInfo tableInfo) {
        String nodeName = tableInfo.getTableName();
        return nodeName;
    }

    public static boolean checkString(String str) {
        // List of field English names
        String[] fieldNames = {
                "operationInductionId",
                "createInductionId",
                "releaseInductionId",
                "archiveInductionId",
                "operateTime",
                "createTime",
                "releaseTime",
                "archiveTime",
                "isValid",
                "spaceId",
                "appId",
                // New field names added here
                "batchStartTime",
                "batchEndTime",
                "subjectLifeCycle",
                "isArchive",
                "archivingType",
                "archivngType",
                "isUpdate",
                "updateStatus",
                "isEditing"
        };


        // Check if str is not equal to any of the field names
        for (String fieldName : fieldNames) {
            if (str.equals(fieldName)) {
                return true;
            }
        }
        return false;
    }

    private Map<String, Object> convert(TableInfo tableInfo) {
        Map<String, Object> nodeData = new HashMap<>();
        nodeData.put("key", getNodeName(tableInfo));
//        if (StringUtils.isNotEmpty(tableInfo.getTableDescription())) {
//            nodeData.put("remark", tableInfo.getTableDescription());
//        } else {
//            nodeData.put("remark", "");
//        }
        List<Map<String, Object>> items = new ArrayList<>();
        for (FieldInfo fieldInfo : tableInfo.getFieldInfoList()) {
            if(fieldInfo.getFieldEnName()!=null && checkString(fieldInfo.getFieldEnName())){
                continue;
            }
            Map<String, Object> item = new HashMap<>();
            if (fieldInfo.getFieldType().equals("1")) {
                item.put("keyType", "PK");
            } else if (fieldInfo.getFieldType().equals("2")) {
                item.put("keyType", "FK");
            } else {
                item.put("keyType", "");
            }
            item.put("keyName", fieldInfo.getFieldName());
//            item.put("keyEnName", fieldInfo.getFieldEnName());
            String length = "";
            if (StringUtils.isNotEmpty(fieldInfo.getMysqlFieldLength())) {
                length = "(" + fieldInfo.getMysqlFieldLength() + ")";
            }
//            item.put("dataType", fieldInfo.getMysqlFieldDataType() + length);
            //item.put("remark", fieldInfo.getFieldStory());
            items.add(item);
        }
        nodeData.put("items", items);
        return nodeData;
    }

    /**
     * 字段设计
     * @param fieldId
     * @param modelMap
     * @return
     */
    @GetMapping("/fieldDesign")
    public String fieldDesign(Long fieldId, ModelMap modelMap) {
        List<FieldInfo> fieldInfoList = this.tableInfoService.selectFieldInfoByFieldId(Arrays.asList(fieldId));
        FieldInfo fieldInfo = fieldInfoList.get(0);
        boolean pkFlag = false;
        boolean fkFlag = false;
        boolean timeFlag = false;
        boolean enumFlag = false;
        boolean otherFlag = false;
        if (fieldInfo.getFieldType().equals("1")) {
            pkFlag = true;
        } else if (fieldInfo.getFieldType().equals("2")) {
            fkFlag = true;
        } else if (fieldInfo.getIsFieldEnum().equals("Y")) {
            enumFlag = true;
            List<SysDictData> sysDictDatas = new ArrayList<>();
            if (fieldInfo.getDictId() != null) {
                SysDictType sysDictType = this.sysDictTypeService.selectDictTypeById(fieldInfo.getDictId());
                if (sysDictType != null) {
                    SysDictData dictData = new SysDictData();
                    dictData.setDictType(sysDictType.getDictType());
                    sysDictDatas = this.sysDictDataService.selectDictDataList(dictData);
                }
            }
            modelMap.put("sysDictDatas", sysDictDatas);
        } else if (fieldInfo.getFieldDataType().equals("3")) {
            timeFlag = true;
        } else {
            otherFlag = true;
        }
        modelMap.put("pkFlag", pkFlag);
        modelMap.put("fkFlag", fkFlag);
        modelMap.put("timeFlag", timeFlag);
        modelMap.put("enumFlag", enumFlag);
        modelMap.put("otherFlag", otherFlag);
        modelMap.put("fieldInfo", fieldInfo);

        return prefix + "/fieldDesign";
    }

    @PostMapping("/updateFieldDesign")
    @ResponseBody
    public AjaxResult updateFieldDesign(FieldInfo fieldInfo) {
        this.tableInfoService.updateFieldDesign(fieldInfo);
        return this.success();
    }

    @GetMapping("/refreshData")
    @ResponseBody
    public AjaxResult refreshData() {
        this.tableInfoService.refreshData();
        return this.success();
    }

    @GetMapping("/tabList/{id}")
    public String tabList(@PathVariable("id") Long tableId,
                          @RequestParam("enname") String tableEnName,
                          @RequestParam("name") String tableName,
                          ModelMap mmap) throws UnsupportedEncodingException{
        mmap.put("tableId", tableId);
        mmap.put("tableEnName", URLDecoder.decode(tableEnName,"UTF-8"));
        mmap.put("tableName", URLDecoder.decode(tableName,"UTF-8"));
        return prefix + "/tabList";
    }

    @GetMapping("/tabUpdate/{id}/{index}")
    public String tabUpdate(@PathVariable("id") Long tableId,
                            @PathVariable("index") int index,
                            @RequestParam("enname") String tableEnName,
                            @RequestParam("name") String tableName,
                            ModelMap mmap) throws UnsupportedEncodingException{
        mmap.put("tableId", tableId);
        mmap.put("index", index);
        mmap.put("tableEnName", URLDecoder.decode(tableEnName,"UTF-8"));
        mmap.put("tableName", URLDecoder.decode(tableName,"UTF-8"));
        return prefix + "/tabUpdate";
    }

    @GetMapping("/tableFieldChoose/{id}")
    public String tableFieldChoose(@PathVariable("id") Long fieldId,
                                   @RequestParam(value = "enname", required = false) String tableEnName,
                            ModelMap mmap){
        mmap.put("fieldId", fieldId);
        mmap.put("enname", tableEnName);
        return prefix + "/tableFieldChoose";
    }

    @GetMapping("/tableFieldBatchChoose")
    public String tableFieldBatchChoose(@RequestParam("tableId") Long tableId, ModelMap mmap) {
        TableInfo tableInfo = new TableInfo();
        if (tableId != null) {
            tableInfo.setExcludeIds(Collections.singletonList(tableId));
        }
        List<TableInfo> tableInfos = this.tableInfoService.selectTableInfoList(tableInfo);
        mmap.put("tableInfoList", tableInfos);
        return prefix + "/table_field_batch_choose";
    }

    @GetMapping("/queryFieldInfoById")
    @ResponseBody
    public AjaxResult queryFieldInfoById(String fieldIds) {
        List<Long> ids = Convert.toLongList(fieldIds);
        Map<Integer, String> tableRelationInfoObj = new HashMap<>();
        List<FieldInfo> fieldInfoList = this.tableInfoService.selectFieldInfoList(ids);
        if (CollectionUtil.isNotEmpty(fieldInfoList)) {
            for (int i = 0; i< fieldInfoList.size(); i++) {
                if ("2".equals(fieldInfoList.get(i).getFieldType())) {
                    TableRelation tableRelation = new TableRelation();
                    tableRelation.setMasterFieldId(fieldInfoList.get(i).getId());
                    List<TableRelation> tableRelationList = this.tableRelationService.selectTableRelationList(tableRelation);
                    if (CollectionUtil.isNotEmpty(tableRelationList)) {
                        fieldInfoList.get(i).setTableRelationListStr(JSONObject.toJSONString(tableRelationList));
                    }
                }
            }
        }
        return AjaxResult.success(fieldInfoList);
    }
}
